{
 "cells": [
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# Creating a publication-quality boxplot (notebook)\n",
    "\n",
    "For a more complete tutorial, please check: https://github.com/jbmouret/matplotlib_for_papers\n",
    "\n",
    "**Objective:** Learn how to compare experimentally two stochastic algorithms (i.e., machine learning algorithms) and produce a figure for a scientific paper\n",
    "\n",
    "*This tutorial relies on Python and the Matplotlib library* (not Matlab)\n",
    "\n",
    "\n",
    "## Example of better vizualization\n",
    "\n",
    "![Modularity boxplot](figs/example1_boxplot.png)\n",
    "\n",
    "From: Clune*, Jeff, Jean-Baptiste Mouret*, and Hod Lipson. \"The evolutionary origins of modularity.\" Proceedings of the Royal Society B: Biological sciences 280.1755 (2013): 20122863 [*: equal contribution].\n",
    "\n",
    "\n",
    "## Use case for Box plot\n",
    "\n",
    "You want to know if \"treatment\" (algorithm) 'A' performs better than treatment 'B'. Since your algorithm is stochastic, you have run replicates (at least 20!) to be sure that one treatment has not been lucky/unlucky, and you want statistically significant results.\n",
    "\n",
    "Other use case: you measure some data (e.g., time to achieve a task) with 20 different user (user study), and you want to know if one approach works better than the other.\n",
    "\n",
    "### Goal:\n",
    "\n",
    "- Display the median and the quartiles\n",
    "- Do not assume that your data are Gaussian (contrary to bars + error bars)\n",
    "\n",
    "See: http://en.wikipedia.org/wiki/Box_plot\n",
    "\n",
    "<img src=\"figs/wikipedia_boxplot.png\" width=\"40%\"/>\n",
    "\n",
    "\n",
    "\n",
    "\n",
    "- Each box extends from the lower to upper quartile values of the data, with a symbol at the median.\n",
    "- Whiskers extend to the most extreme data point within 1.5 * IQR, where IQR is the Inter Quartile Range.\n",
    "- Flier points (outliers) are those past the end of the whiskers.\n",
    "\n",
    "### Median vs mean\n",
    "\n",
    "Using the mean + standard deviation assumes that your data are *normally distributed*. This assumption is usually wrong in \"experimental\" computer science. For instance, your algorithm may fail 30% of the time (performance = 0) and succeed 70% of the time (performance = 1): you have two peaks and the distribution is not Gaussian at all. In addition, the standard deviation assumes that the distribution is symmetric, which is clearly not the case when there is a maximum that cannot be exceeded.\n",
    "\n",
    " **You should always use the median and the 25% / 75% percentiles, unless you have good reason to think that your data are normally distributed**.\n",
    "\n",
    "\n",
    "## Basics: our first boxplot\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: matplotlib in /Users/jmouret/mambaforge/lib/python3.9/site-packages (3.6.2)\n",
      "Requirement already satisfied: cycler>=0.10 in /Users/jmouret/mambaforge/lib/python3.9/site-packages (from matplotlib) (0.11.0)\n",
      "Requirement already satisfied: kiwisolver>=1.0.1 in /Users/jmouret/mambaforge/lib/python3.9/site-packages (from matplotlib) (1.4.4)\n",
      "Requirement already satisfied: numpy>=1.19 in /Users/jmouret/mambaforge/lib/python3.9/site-packages (from matplotlib) (1.23.1)\n",
      "Requirement already satisfied: packaging>=20.0 in /Users/jmouret/mambaforge/lib/python3.9/site-packages (from matplotlib) (21.3)\n",
      "Requirement already satisfied: pillow>=6.2.0 in /Users/jmouret/mambaforge/lib/python3.9/site-packages (from matplotlib) (8.4.0)\n",
      "Requirement already satisfied: pyparsing>=2.2.1 in /Users/jmouret/mambaforge/lib/python3.9/site-packages (from matplotlib) (3.0.9)\n",
      "Requirement already satisfied: python-dateutil>=2.7 in /Users/jmouret/mambaforge/lib/python3.9/site-packages (from matplotlib) (2.8.2)\n",
      "Requirement already satisfied: fonttools>=4.22.0 in /Users/jmouret/mambaforge/lib/python3.9/site-packages (from matplotlib) (4.38.0)\n",
      "Requirement already satisfied: contourpy>=1.0.1 in /Users/jmouret/mambaforge/lib/python3.9/site-packages (from matplotlib) (1.0.6)\n",
      "Requirement already satisfied: six>=1.5 in /Users/jmouret/mambaforge/lib/python3.9/site-packages (from python-dateutil>=2.7->matplotlib) (1.16.0)\n"
     ]
    }
   ],
   "source": [
    "# first we need to install matplotlib\n",
    "# this runs a shell command in a notebook\n",
    "!pip install matplotlib"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Data\n",
    "We assume that the data for each treatment is organized in a in text file (e.g., a CSV), with one file for each result\n",
    "\n",
    "**File1:**\n",
    "||\n",
    "|---|\n",
    "|0.1|\n",
    "|0.24|\n",
    "|...|\n",
    "\n",
    "**File2:**\n",
    "||\n",
    "|---|\n",
    "|0.13|\n",
    "|0.11|\n",
    "|...|\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "metadata": {},
   "outputs": [],
   "source": [
    "import numpy as np\n",
    "\n",
    "# np.loadtxt loads a file as a numpy array\n",
    "data_a = np.loadtxt('src/data_boxplot/a.txt')\n",
    "data_b = np.loadtxt('src/data_boxplot/b.txt')\n",
    "\n",
    "# here we have a single column\n",
    "# for csv (comma separated values), you can use: np.loadtxt('src/data_boxplot/a.txt', delimiter=',')\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "iVBORw0KGgoAAAANSUhEUgAAAmUAAAEvCAYAAAAEpLawAAAAOXRFWHRTb2Z0d2FyZQBNYXRwbG90bGliIHZlcnNpb24zLjUuMSwgaHR0cHM6Ly9tYXRwbG90bGliLm9yZy/YYfK9AAAACXBIWXMAAAsTAAALEwEAmpwYAAAQ4UlEQVR4nO3df+hd933f8dd7UuaEbvbk2CWeZE+GmCJHK9tyMYGGQeZs1saIvZGB8sdsmEA0pGb7Y2x4gjqlBBoKM0u2BMRcEodMTsg2bNqGtSGCInCcfRXS+lc9xEJmzR5TkHA8RlLLffeP73F67VxJsa+k+7nf7+MBF+79nHuu3wIhnj7n3HOruwMAwGr9hVUPAACAKAMAGIIoAwAYgCgDABiAKAMAGIAoAwAYwM5VD7CsG264offu3bvqMQAALunkyZM/6O4bF20bLsqq6kCSf5dkR5L/2N2/cbH37927NxsbG1dlNgCAZVTV9y+0bajTl1W1I8l/SPL3k9ye5GNVdftqpwIAuPKGirIkdyQ51d3/s7v/JMmjSe5e8UwAAFfcaFG2O8kLc69PT2sAAFvaaFFWC9Z+6sc5q+pwVW1U1caZM2euwlgAAFfWaFF2OsnNc6/3JHnxzW/q7qPdPevu2Y03LvwCAwDAWhktyv57ktuq6taq+otJDiZ5fMUzAQBccUPdEqO7z1fVryT5b9m8JcZvdfczKx4LAOCKGyrKkqS7fzfJ7656DgCAq2m005cAANuSKAMAGMBwpy8BYARVi+7StLzun7rTEyQRZQCw0FuJp6oSWyzN6UsAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAH4mSUAtpXrr78+586du+yfe7l/K3PXrl05e/bsZf1MxibKANhWzp07txa/U3mlfhCdcTl9CQAwAFEGADAAUQYAMADXlAGwrfSD1yafvG7VY1xSP3jtqkfgKhNlAGwr9Ws/XJsL/fuTq56Cq8npSwCAAThSxtq7Ul8bX4f/kwZg6xBlrL23Ek9VJbYAGJLTlwAAAxBlAAADEGUAAANwTRkA2846/K7krl27Vj0CV5koA2BbuRJf9vElIi4Hpy8BAAYgygAABiDKAAAGIMoAAAYgygAABiDKAAAGIMoAAAYgygAABiDKAAAG4I7+ALDAW/0ppp/1/e78z4WIMgBYQDxxtTl9CQAwAFEGADAAUQYAMABRBgAwAFEGADCApaKsqv5JVT1TVX9aVbM3bXugqk5V1fNVddfc+vur6qlp22dq+g5xVV1TVV+Z1p+sqr3LzAYAsE6WPVL2dJJ/nOQP5her6vYkB5O8L8mBJJ+rqh3T5s8nOZzktulxYFo/lORcd783yUNJPr3kbAAAa2OpKOvu57r7+QWb7k7yaHf/uLu/l+RUkjuq6qYk13b3E715A5hHktwzt88Xp+dfS3JnvdU79wEArKkrdU3Z7iQvzL0+Pa3tnp6/ef0N+3T3+SQvJ3n3FZoPAGAol7yjf1V9I8l7Fmw60t2PXWi3BWt9kfWL7bNopsPZPAWaW2655QIjAACsj0tGWXd/+G187ukkN8+93pPkxWl9z4L1+X1OV9XOJNclOXuBmY4mOZoks9nM72AAAGvvSp2+fDzJwekblbdm84L+b3f3S0leqaoPTNeL3Zvksbl97puefzTJN9sPjwEA28RSP0heVf8oyWeT3Jjkd6rqu919V3c/U1VfTfJskvNJPtHdr027fTzJF5K8K8nXp0eSPJzkS1V1KptHyA4uMxsAwDqpdT8YNZvNemNjY9VjsCaqKuv+dx6A9VVVJ7t7tmibO/oDAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADECUAQAMQJQBAAxAlAEADGDnqgeAC7n++utz7ty5y/65VXVZP2/Xrl05e/bsZf1MALYfUcawzp07l+5e9RiXdLkjD4DtyelLAIABiDIAgAGIMgCAAYgyAIABiDIAgAEsFWVV9ZtV9cdV9UdV9V+r6q/MbXugqk5V1fNVddfc+vur6qlp22dq+upaVV1TVV+Z1p+sqr3LzAYAsE6WPVL2+0n2d/cvJvkfSR5Ikqq6PcnBJO9LciDJ56pqx7TP55McTnLb9DgwrR9Kcq6735vkoSSfXnI2AIC1sVSUdffvdff56eW3kuyZnt+d5NHu/nF3fy/JqSR3VNVNSa7t7id68wZUjyS5Z26fL07Pv5bkznIDKABgm7ic15T9syRfn57vTvLC3LbT09ru6fmb19+wzxR6Lyd596L/UFUdrqqNqto4c+bMZfsDAACsyiXv6F9V30jyngWbjnT3Y9N7jiQ5n+TLr++24P19kfWL7fPTi91HkxxNktlsNv4t3wEALuGSUdbdH77Y9qq6L8k/THJn//lv4pxOcvPc2/YkeXFa37NgfX6f01W1M8l1SfygIACwLSz77csDSf51ko909/+f2/R4koPTNypvzeYF/d/u7peSvFJVH5iuF7s3yWNz+9w3Pf9okm/2OvzwIQDAZbDsD5L/+yTXJPn96Zr8b3X3L3f3M1X11STPZvO05ie6+7Vpn48n+UKSd2XzGrTXr0N7OMmXqupUNo+QHVxyNgCAtVHrfjBqNpv1xsbGqsfgCqiqrMPfz3WZE4DVq6qT3T1btM0d/QEABiDKAAAGIMoAAAYgygAABrDsty/hiukHr00+ed2qx7ikfvDaVY8AwBYgyhhW/doP1+JbjVWV/uSqpwBg3Tl9CQAwAFEGADAAUQYAMABRBgAwAFEGADAAUQYAMABRBgAwAFEGADAAUQYAMABRBgAwAFEGADAAUQYAMABRBgAwAFEGADAAUQYAMABRBgAwAFEGADAAUQYAMABRBgAwAFEGADAAUQYAMABRBgAwAFEGADAAUQYAMABRBgAwgJ2rHgAupqpWPcIl7dq1a9UjALAFiDKG1d2X/TOr6op8LgAsy+lLAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAEsFWVV9etV9UdV9d2q+r2q+qtz2x6oqlNV9XxV3TW3/v6qemra9pmafnG6qq6pqq9M609W1d5lZgMAWCfLHin7ze7+xe7+G0l+O8mvJklV3Z7kYJL3JTmQ5HNVtWPa5/NJDie5bXocmNYPJTnX3e9N8lCSTy85GwDA2lgqyrr7h3Mvfy5JT8/vTvJod/+4u7+X5FSSO6rqpiTXdvcT3d1JHklyz9w+X5yefy3Jna8fRQMA2Op2LvsBVfWpJPcmeTnJh6bl3Um+Nfe209Paq9PzN6+/vs8LSdLd56vq5STvTvKDZWcEABjdJY+UVdU3qurpBY+7k6S7j3T3zUm+nORXXt9twUf1RdYvts+imQ5X1UZVbZw5c+ZSfwQAgOFd8khZd3/4Z/ys/5Tkd5I8mM0jYDfPbduT5MVpfc+C9cztc7qqdia5LsnZC8x0NMnRJJnNZgvDDQBgnSz77cvb5l5+JMkfT88fT3Jw+kblrdm8oP/b3f1Skleq6gPT9WL3Jnlsbp/7pucfTfLN6bozAIAtb9lryn6jqn4hyZ8m+X6SX06S7n6mqr6a5Nkk55N8ortfm/b5eJIvJHlXkq9PjyR5OMmXqupUNo+QHVxyNgCAtVHrfjBqNpv1xsbGqsdgTVRV1v3vPADrq6pOdvds0TZ39AcAGIAoAwAYgCgDABjA0jePhVV7qz/88LO+37VnAFxNooy1J54A2AqcvgQAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGIAoAwAYgCgDABiAKAMAGMBlibKq+pdV1VV1w9zaA1V1qqqer6q75tbfX1VPTds+U1U1rV9TVV+Z1p+sqr2XYzYAgHWwdJRV1c1J/m6S/zW3dnuSg0nel+RAks9V1Y5p8+eTHE5y2/Q4MK0fSnKuu9+b5KEkn152NgCAdXE5jpQ9lORfJem5tbuTPNrdP+7u7yU5leSOqropybXd/UR3d5JHktwzt88Xp+dfS3Ln60fRAAC2uqWirKo+kuR/d/cfvmnT7iQvzL0+Pa3tnp6/ef0N+3T3+SQvJ3n3MvMBAKyLnZd6Q1V9I8l7Fmw6kuTfJPl7i3ZbsNYXWb/YPotmOpzNU6C55ZZbFr0FAGCtXDLKuvvDi9ar6q8nuTXJH05nGfck+U5V3ZHNI2A3z719T5IXp/U9C9Yzt8/pqtqZ5LokZy8w09EkR5NkNpstDDcAgHXytk9fdvdT3f3z3b23u/dmM6r+Vnf/nySPJzk4faPy1mxe0P/t7n4pyStV9YHperF7kzw2feTjSe6bnn80yTen684AALa8Sx4pezu6+5mq+mqSZ5OcT/KJ7n5t2vzxJF9I8q4kX58eSfJwki9V1alsHiE7eCVmAwAYUa37wajZbNYbGxurHgMA4JKq6mR3zxZtc0d/AIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDIAgAGIMgCAAYgyAIABiDK2hWPHjmX//v3ZsWNH9u/fn2PHjq16JAB4g52rHgCutGPHjuXIkSN5+OGH88EPfjAnTpzIoUOHkiQf+9jHVjwdAGyq7l71DEuZzWa9sbGx6jEY2P79+/PZz342H/rQh36ydvz48dx///15+umnVzgZANtNVZ3s7tnCbaKMrW7Hjh350Y9+lHe84x0/WXv11Vfzzne+M6+99toKJwNgu7lYlLmmjC1v3759OXHixBvWTpw4kX379q1oIgD4aaKMLe/IkSM5dOhQjh8/nldffTXHjx/PoUOHcuTIkVWPBgA/4UJ/trzXL+a///7789xzz2Xfvn351Kc+5SJ/AIbimjIAgKvENWUAAIMTZQAAAxBlAAADEGUAAAMQZQAAAxBlAAADEGUAAAMQZQAAA1j7m8dW1Zkk31/1HKyNG5L8YNVDAFuOf1v4Wf217r5x0Ya1jzJ4K6pq40J3UgZ4u/zbwuXg9CUAwABEGQDAAEQZ283RVQ8AbEn+bWFprikDABiAI2UAAAMQZWwLVfVbVfV/q+rpVc8CbA1VdXNVHa+q56rqmar656ueifXm9CXbQlX97ST/L8kj3b1/1fMA66+qbkpyU3d/p6r+cpKTSe7p7mdXPBprypEytoXu/oMkZ1c9B7B1dPdL3f2d6fkrSZ5Lsnu1U7HORBkALKmq9ib5m0meXPEorDFRBgBLqKq/lOQ/J/kX3f3DVc/D+hJlAPA2VdU7shlkX+7u/7LqeVhvogwA3oaqqiQPJ3muu//tqudh/YkytoWqOpbkiSS/UFWnq+rQqmcC1t4vJfmnSf5OVX13evyDVQ/F+nJLDACAAThSBgAwAFEGADAAUQYAMABRBgAwAFEGADAAUQYAMABRBgAwAFEGADCAPwOIPZ8Q6P1wSwAAAABJRU5ErkJggg==",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib.pyplot as plt\n",
    "\n",
    "fig = plt.figure(figsize=(10, 5))\n",
    "ax = fig.add_subplot(1,1,1)\n",
    "ax.boxplot([data_a, data_b])\n",
    "\n",
    "fig.savefig('fig.pdf') # we create a PDF file for inclusion in a paper (vector format)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Storing figures: Vector format versus bitmap format\n",
    "\n",
    "- Vector formats (pdf, svg, eps): store the coordinates of graphic objects (e.g., lines, circles)\n",
    "\n",
    "\n",
    "<img src=\"https://dev.w3.org/SVG/tools/svgweb/samples/svg-files/atom.svg\" alt=\"svf\" style=\"width: 240px;\"/>\n",
    "\n",
    "\n",
    "```svg\n",
    "<svg xmlns=\"http://www.w3.org/2000/svg\" viewBox=\"-52 -53 100 100\" stroke-width=\"2\">\n",
    " <g fill=\"none\">\n",
    "  <ellipse stroke=\"#66899a\" rx=\"6\" ry=\"44\"/>\n",
    "  <ellipse stroke=\"#e1d85d\" rx=\"6\" ry=\"44\" transform=\"rotate(-66)\"/>\n",
    "  <ellipse stroke=\"#80a3cf\" rx=\"6\" ry=\"44\" transform=\"rotate(66)\"/>\n",
    "  <circle stroke=\"#4b541f\" r=\"44\"/>\n",
    " </g>\n",
    " ...\n",
    "</svg>\n",
    "```\n",
    "- Bitmap formats (png, jpg, bmp, ...): store the pixels (for jpg: lossy compression; for png: lossless compression)\n",
    "```\n",
    "P1\n",
    "# feep.pbm\n",
    "24 7\n",
    "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
    "0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 1 1 1 0\n",
    "0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 1 0\n",
    "0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 0 0 0 1 1 1 1 0\n",
    "0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0 0 1 0 0 0 0\n",
    "0 1 0 0 0 0 0 1 1 1 1 0 0 1 1 1 1 0 0 1 0 0 0 0\n",
    "0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0\n",
    "```\n",
    "\n",
    "- **Vector formats are more appropriate for plots (except with millions of points):**\n",
    "  - they are often smaller\n",
    "  - you can zoom without ever \"see the pixels\"\n",
    "  \n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "# How to make this figure better?\n",
    "\n",
    "<img src=\"figs/tufte_book_cover.png\" width=\"200px\" align=\"left\" hspace=\"30\" vspace=\"5\">\n",
    "\n",
    "Probably the most influential book about data vizualization:\n",
    "\n",
    "Tufte, Edward R. *The visual display of quantitative information.*, 2nd edition, Cheshire, CT: Graphics press, 2001.\n",
    "\n",
    "**Main principle:** maximize the data / ink ratio. In other words, minimize the visual clutter, or remove everything that is not useful to understand the data.\n",
    "\n",
    "Example of bad vizualizations:\n",
    " - http://joeloughton.com/blog/wp-content/uploads/2011/04/chart13.gif [from: http://joeloughton.com/blog/]\n",
    " - http://www.forbes.com/sites/naomirobbins/2012/05/30/winner-of-the-bad-graph-contest-announced-2/\n",
    "\n",
    "Examples of a better vizualization (according to Tufte):\n",
    " - http://www.edwardtufte.com/bboard/q-and-a-fetch-msg?msg_id=00014g\n",
    " - http://joeloughton.com/blog/visualisations/tufte-bar-chart-redesign-in-jquery-flot/\n",
    " - http://blog.revolutionanalytics.com/2010/03/white-house-taps-edward-tufte-to-explain-the-stimulus.html\n",
    "\n",
    "<center><img src=\"https://miro.medium.com/max/1400/1*_2SEqWI_sS3lleOgjUhiwQ.webp\" width=\"50%\"></center>\n",
    "\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "# As a rule of thumb, the font size of your labels should be close to the font size of the figure's caption.\n",
    "\n",
    "# It is also a good idea to increase the linewidths, to be able to make the figure small:\n",
    "import matplotlib as mpl\n",
    "\n",
    "params = {\n",
    "'axes.labelsize': 16,\n",
    "'legend.fontsize': 16,\n",
    "'xtick.labelsize': 16,\n",
    "'ytick.labelsize': 16,\n",
    "}\n",
    "mpl.rcParams.update(params)\n",
    "\n",
    "\n",
    "fig = plt.figure(figsize=(10, 5))\n",
    "ax = fig.add_subplot(1,1,1)\n",
    "bp = ax.boxplot([data_a, data_b])\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 720x360 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib as mpl\n",
    "\n",
    "params = {\n",
    "'axes.labelsize': 16,\n",
    "'legend.fontsize': 16,\n",
    "'xtick.labelsize': 16,\n",
    "'ytick.labelsize': 16,\n",
    "}\n",
    "mpl.rcParams.update(params)\n",
    "\n",
    "\n",
    "fig = plt.figure(figsize=(10, 5))\n",
    "ax = fig.add_subplot(1,1,1)\n",
    "bp = ax.boxplot([data_a, data_b])\n",
    "\n",
    "# remove the frames \n",
    "ax.spines['top'].set_visible(False)\n",
    "ax.spines['right'].set_visible(False)\n",
    "ax.spines['left'].set_visible(False)\n",
    "ax.get_xaxis().tick_bottom()\n",
    "ax.get_yaxis().tick_left()\n",
    "ax.tick_params(axis='x', direction='out')\n",
    "ax.tick_params(axis='y', length=0)\n",
    "\n",
    "# add a grid\n",
    "\n",
    "ax.grid(axis='y', color=\"0.9\", linestyle='-', linewidth=1)\n",
    "ax.set_axisbelow(True)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Adding color..."
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": [
    "\n",
    " from palettable.colorbrewer.qualitative import Set2_7\n",
    " colors = Set2_7.mpl_colors\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "[Text(1, 0, 'A'), Text(2, 0, 'B')]"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib as mpl\n",
    "\n",
    "\n",
    "from palettable.colorbrewer.qualitative import Set2_7\n",
    "colors = Set2_7.mpl_colors\n",
    "\n",
    "params = {\n",
    "'axes.labelsize': 16,\n",
    "'legend.fontsize': 16,\n",
    "'xtick.labelsize': 16,\n",
    "'ytick.labelsize': 16,\n",
    "}\n",
    "mpl.rcParams.update(params)\n",
    "\n",
    "\n",
    "fig = plt.figure(figsize=(6, 4))\n",
    "ax = fig.add_subplot(1,1,1)\n",
    "bp = ax.boxplot([data_a, data_b], patch_artist=True)\n",
    "\n",
    "# remove the frames \n",
    "ax.spines['top'].set_visible(False)\n",
    "ax.spines['right'].set_visible(False)\n",
    "ax.spines['left'].set_visible(False)\n",
    "ax.spines['bottom'].set_linewidth(2)\n",
    "#ax.spines['bottom'].set_visible(False)\n",
    "\n",
    "ax.get_xaxis().tick_bottom()\n",
    "ax.get_yaxis().tick_left()\n",
    "ax.tick_params(axis='x', length=0)\n",
    "ax.tick_params(axis='y', length=0)\n",
    "\n",
    "# add a grid\n",
    "\n",
    "ax.grid(axis='y', color=\"0.9\", linestyle='-', linewidth=1)\n",
    "ax.set_axisbelow(True)\n",
    "\n",
    "c=colors[0]\n",
    "for w in bp['whiskers']:\n",
    "    w.set_color(c)\n",
    "    w.set_linewidth(3)\n",
    "for patch in bp['boxes']:\n",
    "    patch.set_facecolor(c)\n",
    "    patch.set_color(c)\n",
    "for median in bp['medians']:\n",
    "    median.set(color ='black',\n",
    "                linewidth = 2)\n",
    "\n",
    "ax.set_xticklabels(['A', 'B'])\n",
    "#ax.xaxis.set_tick_params(fontproperties=)\n",
    "\n"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": []
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "## Adding the stars for statistical significance\n",
    "\n",
    "When comparing two treatments, we usually use stars to represent the p-value that results from a (well-chosen) statistical test.  \"Informally, a p-value is the probability under a specified statistical model that a statistical summary of the data (e.g., the sample mean difference between two compared groups) would be equal to or more extreme than its observed value\" (https://amstat.tandfonline.com/doi/full/10.1080/00031305.2016.1154108#_i27)\n",
    "\n",
    "P-values do not measure the probability that the studied hypothesis is true, or the probability that the data were produced by random chance alone.\n",
    "\n",
    "\n",
    "There are *parametric* statistical tests (which assumes that the distribution of the data is known) and *non-parametric* tests (which do not assume that the distribution is known). The classic Student's t-test (http://en.wikipedia.org/wiki/Student's_t-test) is a parametric test that only works when the data are normally distributed. *As explained before, data are rarely normally distributed when we compare algorithms* (but this is often the case in biology or in physics). A good non-parametric alternative to the t-test is the **Mann-Whitney U-test** (http://en.wikipedia.org/wiki/Mann%E2%80%93Whitney_U_test) (called ranksum in matlab, or Wilcoxon test, or Man-Whitney-Wilcoxon).\n",
    "\n",
    "In python, there is an implementation in Scipy (a scientific package on top of numpy; if you don't have it yet: sudo pip install scipy or apt-get install it):\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 43,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "Requirement already satisfied: scipy in /Users/jmouret/mambaforge/envs/matplotlib/lib/python3.10/site-packages (1.7.3)\n",
      "Requirement already satisfied: numpy<1.23.0,>=1.16.5 in /Users/jmouret/mambaforge/envs/matplotlib/lib/python3.10/site-packages (from scipy) (1.22.0)\n"
     ]
    }
   ],
   "source": [
    "!pip install scipy"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 50,
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "9.918628618948002e-11\n"
     ]
    }
   ],
   "source": [
    "import scipy.stats\n",
    "_, p = scipy.stats.mannwhitneyu(data_a, data_b)\n",
    "print(p)"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "<img src=\"https://imgs.xkcd.com/comics/p_values_2x.png\" width=\"300px\"/>"
   ]
  },
  {
   "cell_type": "markdown",
   "metadata": {},
   "source": [
    "### Why are p-values dangerous?\n",
    "P-values compare the distributions... but not the effect size! \n",
    "\n",
    "A small p-values says that the two set of numbers are statistically different, but not that this difference is meaningful for your scientific experiment. In addition, be careful about all the uncertainty implied by the choice of the hyperparameters and the \"fishing experiments\".\n",
    "\n",
    "In many cases, you can make the p-value smaller by adding replicates; but if you need 1 million replicates to see the difference between algorithm A and algorithm B, is it really interesting?\n",
    "\n",
    "See: https://amstat.tandfonline.com/doi/full/10.1080/00031305.2016.1154108#_i27\n",
    "\n",
    "<img src=\"https://imgs.xkcd.com/comics/significant.png\" width=\"60%\">"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 51,
   "metadata": {},
   "outputs": [],
   "source": [
    "def stars(p):\n",
    "    if p < 0.0001:\n",
    "        return \"****\"\n",
    "    elif (p < 0.001):\n",
    "        return \"***\"\n",
    "    elif (p < 0.01):\n",
    "        return \"**\"\n",
    "    elif (p < 0.05):\n",
    "        return \"*\"\n",
    "    else:\n",
    "        return \"-\"\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 65,
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "Text(1.5, 750, '****')"
      ]
     },
     "execution_count": 65,
     "metadata": {},
     "output_type": "execute_result"
    },
    {
     "data": {
      "image/png": "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",
      "text/plain": [
       "<Figure size 432x288 with 1 Axes>"
      ]
     },
     "metadata": {
      "needs_background": "light"
     },
     "output_type": "display_data"
    }
   ],
   "source": [
    "import matplotlib as mpl\n",
    "\n",
    "\n",
    "from palettable.colorbrewer.qualitative import Set2_7\n",
    "colors = Set2_7.mpl_colors\n",
    "\n",
    "params = {\n",
    "'axes.labelsize': 16,\n",
    "'legend.fontsize': 16,\n",
    "'xtick.labelsize': 16,\n",
    "'ytick.labelsize': 16,\n",
    "}\n",
    "mpl.rcParams.update(params)\n",
    "\n",
    "\n",
    "fig = plt.figure(figsize=(6, 4))\n",
    "ax = fig.add_subplot(1,1,1)\n",
    "bp = ax.boxplot([data_a, data_b], patch_artist=True)\n",
    "\n",
    "# remove the frames \n",
    "ax.spines['top'].set_visible(False)\n",
    "ax.spines['right'].set_visible(False)\n",
    "ax.spines['left'].set_visible(False)\n",
    "ax.spines['bottom'].set_linewidth(2)\n",
    "#ax.spines['bottom'].set_visible(False)\n",
    "\n",
    "ax.get_xaxis().tick_bottom()\n",
    "ax.get_yaxis().tick_left()\n",
    "ax.tick_params(axis='x', length=0)\n",
    "ax.tick_params(axis='y', length=0)\n",
    "\n",
    "# add a grid\n",
    "\n",
    "ax.grid(axis='y', color=\"0.9\", linestyle='-', linewidth=1)\n",
    "ax.set_axisbelow(True)\n",
    "\n",
    "c=colors[0]\n",
    "for w in bp['whiskers']:\n",
    "    w.set_color(c)\n",
    "    w.set_linewidth(3)\n",
    "for patch in bp['boxes']:\n",
    "    patch.set_facecolor(c)\n",
    "    patch.set_color(c)\n",
    "for median in bp['medians']:\n",
    "    median.set(color ='black',\n",
    "                linewidth = 2)\n",
    "\n",
    "ax.set_xticklabels(['A', 'B'])\n",
    "ax.set_ylim((-5000, 1000))\n",
    "_, p = scipy.stats.mannwhitneyu(data_a, data_b)\n",
    "y_max = np.max(np.concatenate((data_a, data_b)))\n",
    "ax.annotate(\"\", xy=(1, y_max), xycoords='data',\n",
    "        xytext=(2, y_max), textcoords='data',\n",
    "        arrowprops=dict(arrowstyle=\"-\", ec='#bbbbbb',\n",
    "                        connectionstyle=\"bar,fraction=0.15\"))\n",
    "ax.text(1.5, 750, stars(p), horizontalalignment='center', verticalalignment='center')\n",
    "\n"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3.10.4 ('matplotlib')",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.10.4"
  },
  "orig_nbformat": 4,
  "vscode": {
   "interpreter": {
    "hash": "1e02c40b056f4c06cbeedbaa9e141b948e222bbb153cd5a01f526155b70af844"
   }
  }
 },
 "nbformat": 4,
 "nbformat_minor": 2
}
